package cd.cdyb.sms.service.impl;


import cd.cdyb.sms.config.LoginUserSecurityDto;
import cd.cdyb.sms.dao.CompanyDao;
import cd.cdyb.sms.dao.EmployeeDao;
import cd.cdyb.sms.domain.Company;
import cd.cdyb.sms.domain.Employee;
import cd.cdyb.sms.dto.AccessTokenModel;
import cd.cdyb.sms.dto.EmployeeDto;
import cd.cdyb.sms.exception.BusinessException;
import cd.cdyb.sms.service.EmployeeService;
import cd.cdyb.sms.service.RedisService;
import cd.cdyb.sms.service.SystemLogService;
import cd.cdyb.sms.utils.BeanUtilPlus;
import cd.cdyb.sms.utils.CacheUtils;
import cd.cdyb.sms.vo.EmployeeVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.http.client.utils.URIBuilder;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod;
import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestClientResponseException;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.net.URI;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

/**
 * @author lilin
 */
@Service("employeeService")
public class EmployeeServiceImpl implements EmployeeService {

    private final static Logger log = LogManager.getLogger(LogManager.ROOT_LOGGER_NAME);

    @Resource
    private EmployeeDao employeeDao;

    @Resource
    private RestTemplate restTemplate;


    @Value("${server.port}")
    private String port;

    @Value("${server.servlet.context-path}")
    private String contextPath;

    @Resource
    private RedisService redisService;

    @Resource
    private SystemLogService systemLogService;

    @Override
    public LoginUserSecurityDto login(String username, String password) throws BusinessException {
        LambdaQueryWrapper<Employee> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Employee::getUsername, username);
        Employee employee = employeeDao.selectOne(wrapper);
        if (Objects.isNull(employee)) {
            throw new BusinessException("企业不存在");
        }
        log.info("用户[{}]登录,密码[{}]", username, password);

        LoginUserSecurityDto loginUserSecurityDto = new LoginUserSecurityDto();
        String accessToken = this.generateAccessToken("CLIENT@"+username, password);
        loginUserSecurityDto.setUsername(employee.getUsername());
        loginUserSecurityDto.setId(employee.getCompanyId());
        loginUserSecurityDto.setAccessToken(accessToken);
        loginUserSecurityDto.setPhone(employee.getPhone());
        return loginUserSecurityDto;
    }

    @Override
    public void insert(EmployeeDto employeeDto) throws BusinessException {
        Integer count = employeeDao.selectCount(new LambdaQueryWrapper<Employee>()
                .eq(Employee::getPhone, employeeDto.getPhone()));
        if (count > 0) {
            throw new BusinessException("当前联系方式已经存在:" + employeeDto.getPhone());
        }
        Employee employee = BeanUtilPlus.copyAs(employeeDto, Employee.class);
        employeeDao.insert(employee);
    }

    @Override
    public void update(EmployeeDto employeeDto) throws BusinessException {
        Employee employee = employeeDao.selectById(employeeDto.getEmployeeId());
        if (Objects.isNull(employee)) {
            throw new BusinessException("当前用户不存在:" + employeeDto.getPhone());
        }
        if (!employeeDto.getPhone().equals(employee.getPhone())) {
            Integer count = employeeDao.selectCount(new LambdaQueryWrapper<Employee>()
                    .eq(Employee::getPhone, employeeDto.getPhone()));
            if (count > 0) {
                throw new BusinessException("当前联系方式已经存在:" + employeeDto.getPhone());
            }
        }
        employee.setUpdateTime(LocalDateTime.now());
        employee.setPhone(employeeDto.getPhone());
        employee.setUsername(employeeDto.getUsername());
        employeeDao.updateById(employee);
    }

    @Override
    public void valid(EmployeeDto employeeDto) throws BusinessException {
        Employee employee = employeeDao.selectById(employeeDto.getEmployeeId());
        if (Objects.isNull(employee)) {
            throw new BusinessException("当前用户不存在");
        }
        employeeDao.updateById(employee);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleted(EmployeeDto employeeDto) throws BusinessException {
        Employee employee = employeeDao.selectById(employeeDto.getEmployeeId());
        if (Objects.isNull(employee)) {
            throw new BusinessException("当前用户不存在");
        }
        employeeDao.deleteById(employeeDto.getEmployeeId());
        systemLogService.insert(3, "删除人员，人员姓名：" + employee.getUsername() + "；人员联系方式：" + employee.getPhone());
    }

    @Override
    public List<EmployeeVo> findEmployeeList(EmployeeDto employeeDto) {
        return employeeDao.findEmployeeList(employeeDto);
    }


    public String generateAccessToken(String username, String password) throws BusinessException {
        try {
            String uri = "http://127.0.0.1:" + port + contextPath + "/oauth/token?client_id=helpCenter&client_secret=123456&grant_type=password&username={username}&password={password}"
                    .replace("{username}", username)
                    .replace("{password}", password);
            URI resetPwdUri = new URIBuilder(uri).build();

            RequestEntity requestEntity = new RequestEntity(HttpMethod.POST, resetPwdUri);
            ResponseEntity<AccessTokenModel> responseEntity = restTemplate.exchange(requestEntity, AccessTokenModel.class);


            return responseEntity.getBody().getData().getAccessToken();
        } catch (RestClientResponseException e) {
            log.error("generateAccessToken RestClientResponseException error:", e);
            if (e.getResponseBodyAsString().contains("User is disabled")) {
                throw new BusinessException("error.visitor.usernameOrPasswordInvalid", "账号或密码错误!");
            } else {
                throw new BusinessException("error.visitor.usernameOrPasswordInvalid", "账号或密码错误!");
            }
        } catch (Exception e) {
            log.error("generateAccessToken other error:", e);
            throw new BusinessException("error.visitor.usernameOrPasswordInvalid", "账号或密码错误!");
        }
    }

}
